#ifndef PFS_FILE_NAME_SYSTEM_H
#define PFS_FILE_NAME_SYSTEM_H
#include "inode.h"
#include "file_list.h"
#include "block_file.h"
#include <string>
#include <cstring>
#include <stdint.h>
#include <Lock.h>
using namespace std;

namespace PFS
{
    class FileNameSystem
    {
        public:
            FileNameSystem();
            virtual ~FileNameSystem();
            void add_node(INode* node, INode* parent);//no matter node is dict or file,just add it to parent
            void add_node(const string& path, INode* node);//find its parent first
            inline INode* get_root()
            { return root; }
            inline string get_pwd(const string &path)
            {
                return path.substr(0, path.find_last_of(DELEMIT));    
            }
            INode* find_node_by_path(const string& path);
            INode* find_node_by_name(const string& name, const INode* parent);
            INode* find_file(const string& file_name,const INode* parent);
            INode* find_file(const string& file_name);
            INode* find_file_by_block(const uint32_t block_id);
            void add_block(const uint32_t block_id, BlockLocate *block);
            void add_block(BlockLocate *block, INode* node);
            bool exsit_block(const uint32_t block_id);
            BlockLocate* find_block(const uint32_t block_id);
            void remove_block(const uint32_t block_id);
            void remove_block(const uint32_t block_id, INode* node);
            BlockLocate* replace_block(const uint32_t block_id, BlockLocate* new_blk);
            BlockLocate* create_block(const string &file_name, const uint32_t block_id);
            void remove_node_by_path(const string& path, bool force_del = false);
            void remove_node_by_name(const string& name, INode* parent, bool force_del = false);
            void rename_by_path(const string& path, const string& new_name);//no change its parent path
            inline bool is_leaf(const INode& node) const
            {
                return (!node.is_directory());
            }

            inline uint64_t get_block_num() const
            {
                return block_file_list.get_block_num();
            }

        private:
            INode *root;
            FileList file_list;
            Block2File block_file_list;
            uint64_t file_count;
            uint32_t dir_count;
            RWLock rw_lock;
    };
}
#endif
